home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 1
/
Amiga Tools.iso
/
disk-tools
/
cd-tools
/
amicdrom
/
devsupp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-06
|
14KB
|
513 lines
/* devsupp.c:
*
* Support routines for the device handler.
* - debugging
* - Mountlist "Startup" field parsing
*
* ----------------------------------------------------------------------
* This code is (C) Copyright 1993,1994 by Frank Munkert.
* All rights reserved.
* This software may be freely distributed and redistributed for
* non-commercial purposes, provided this notice is included.
* ----------------------------------------------------------------------
* History:
*
* 09-Apr-94 fmu Larger buffer for startup strings.
* 02-Jan-94 fmu New options XPOS and YPOS.
* 11-Dec-93 fmu Memory type can now be chosen by the user:
* new options CHIP, DMA and ANY.
* 11-Dec-93 fmu The assembly code stubs for the debugging process
* are no longer necessary; the debugger code is now
* called with CreateNewProcTags().
* 21-Nov-93 fmu New option SCANINTERVAL.
* 14-Nov-93 fmu Added Handle_Control_Packet for 'cdcontrol' program.
* 10-Nov-93 fmu New options SHOWVERSION and HFSFIRST.
* 23-Oct-93 fmu MacHFS options added.
* 15-Oct-93 fmu Adapted to new VOLUME structure.
*/
/*
* Extract information from Mountlist "Startup" field.
*/
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#ifdef _DCC
#define abs
#endif
#include <exec/types.h>
#include <dos/dostags.h>
#include <clib/dos_protos.h>
#include "device.h"
#include "devsupp.h"
#include "intui.h"
#include "params.h"
#include "cdcontrol.h"
static char *TheVersion = "$VER: " VERSION;
unsigned long g_memory_type;
int
Get_Startup (LONG p_startup)
{
enum {
ARG_DEVICE,
ARG_UNIT,
ARG_CHIP,
ARG_FAST,
ARG_DMA,
ARG_ANY,
ARG_LOWERCASE,
ARG_ROCKRIDGE,
ARG_TRACKDISK,
ARG_MACTOISO,
ARG_CONVERTSPACES,
ARG_SHOWVERSION,
ARG_HFSFIRST,
ARG_STDBUFFERS,
ARG_FILEBUFFERS,
ARG_DATAEXT,
ARG_RESOURCEEXT,
ARG_SCANINTERVAL,
ARG_PLAYCDDA,
ARG_XPOS,
ARG_YPOS,
ARGCOUNT
};
STRPTR Args[ARGCOUNT],Index;
UBYTE LocalBuffer[250];
struct RDArgs *ArgsPtr;
int result = FALSE,len,i;
int cnt;
/* Clear the argument vector. */
memset (Args, 0, sizeof(Args));
/* valid startup entry? */
if (!p_startup) {
Display_Error ("Filesystem startup entry invalid");
return FALSE;
}
/* Get the contents of the startup field. */
len = ((STRPTR)(BADDR(p_startup)))[0];
if (len > sizeof (LocalBuffer) - 1)
len = sizeof (LocalBuffer) - 1;
memcpy (LocalBuffer, ((STRPTR)(BADDR(p_startup))) + 1, len);
/* Provide null-termination. */
LocalBuffer[len] = 0;
/* Remove leading quotes. */
for (i = 0 ; i < len ; i++) {
if (LocalBuffer[i] != ' ') {
if (LocalBuffer[i] == '\"')
LocalBuffer[i] = ' ';
break;
}
}
/* Remove trailing quotes. */
for (i = len - 1 ; i >= 0 ; i--) {
if (LocalBuffer[i] != ' '){
if (LocalBuffer[i] == '\"')
LocalBuffer[i] = ' ';
break;
}
}
/* Replace "-" by spaces, except "--" which is replaced by "-". */
Index = LocalBuffer;
for (i = 0 ; i < len ; i++) {
if (LocalBuffer[i] == '-') {
if (i+1 < len && LocalBuffer[i+1] == '-') {
*Index++ = '-';
i++;
} else
*Index++ = ' ';
} else
*Index++ = LocalBuffer[i];
}
/* Provide null-termination. */
*Index = 0;
/* Don't forget the newline, or ReadArgs won't work. */
strcat ((char *) LocalBuffer, "\n");
if (ArgsPtr = (struct RDArgs *) AllocDosObjectTags (DOS_RDARGS,TAG_DONE)) {
/* Don't prompt for input! */
ArgsPtr -> RDA_Flags |= RDAF_NOPROMPT;
/* Set up for local parsing. */
ArgsPtr->RDA_Source.CS_Buffer = LocalBuffer;
ArgsPtr->RDA_Source.CS_Length = strlen ((char *) LocalBuffer);
ArgsPtr->RDA_Source.CS_CurChr = 0;
/* Read the arguments. */
if (ReadArgs ((UBYTE *)
"D=DEVICE,U=UNIT/N,C=CHIP/S,F=FAST/S,DMA/S,ANY/S,"
"L=LOWERCASE/S,"
"R=ROCKRIDGE/S,T=TRACKDISK/S,"
"MI=MACTOISO/S,CS=CONVERTSPACES/S,"
"SV=SHOWVERSION/S,HF=HFSFIRST/S,"
"SB=STDBUFFERS/K/N,FB=FILEBUFFERS/K/N,"
"DE=DATAEXT/K,RE=RESOURCEEXT/K,"
"SI=SCANINTERVAL/K/N,PC=PLAYCDDA/K,"
"X=XPOS/K/N,Y=YPOS/K/N",
(LONG *) Args, ArgsPtr)) {
result = TRUE;
if (Args[ARG_DEVICE]) {
len = strlen((char *) (Args[ARG_DEVICE]));
if (len >= sizeof (g_device)) {
Display_Error ("Device name entry too long");
result = FALSE;
} else
strcpy (g_device, (char *) (Args[ARG_DEVICE]));
} else
Display_Error("Device name entry missing");
g_unit = *(long *) (Args[ARG_UNIT]);
g_memory_type = MEMF_CHIP;
cnt = 0;
if (Args[ARG_FAST] != NULL) {
g_memory_type = MEMF_FAST;
cnt++;
}
if (Args[ARG_CHIP] != NULL) {
g_memory_type = MEMF_CHIP;
cnt++;
}
if (Args[ARG_DMA] != NULL) {
g_memory_type = MEMF_24BITDMA;
cnt++;
}
if (Args[ARG_ANY] != NULL) {
g_memory_type = MEMF_ANY;
cnt++;
}
if (cnt > 1) {
Display_Error ("Only ONE memory option may be used!");
result = FALSE;
}
g_map_to_lowercase = (Args[ARG_LOWERCASE] != NULL);
g_use_rock_ridge = (Args[ARG_ROCKRIDGE] != NULL);
g_trackdisk = (Args[ARG_TRACKDISK] != NULL);
g_show_version_numbers = (Args[ARG_SHOWVERSION] != NULL);
g_hfs_first = (Args[ARG_HFSFIRST] != NULL);
if (Args[ARG_STDBUFFERS]) {
g_std_buffers = *(long *) (Args[ARG_STDBUFFERS]);
if (g_std_buffers <= 0) {
Display_Error ("Illegal number of standard buffers: %ld", g_std_buffers);
result = FALSE;
}
} else
g_std_buffers = 5;
if (Args[ARG_FILEBUFFERS]) {
g_file_buffers = *(long *) (Args[ARG_FILEBUFFERS]);
if (g_file_buffers <= 0) {
Display_Error ("Illegal number of file buffers: %ld", g_std_buffers);
result = FALSE;
}
} else
g_file_buffers = 5;
if (Args[ARG_DATAEXT])
strcpy (g_data_fork_extension, (char *) Args[ARG_DATAEXT]);
if (Args[ARG_RESOURCEEXT])
strcpy (g_resource_fork_extension, (char *) Args[ARG_RESOURCEEXT]);
g_convert_hfs_filenames = (Args[ARG_MACTOISO] != NULL);
g_convert_hfs_spaces = (Args[ARG_CONVERTSPACES] != NULL);
if (Args[ARG_SCANINTERVAL]) {
g_scan_interval = *(long *) (Args[ARG_SCANINTERVAL]);
if (g_scan_interval < 0)
g_scan_interval = 0;
} else
g_scan_interval = 3;
if (Args[ARG_PLAYCDDA]) {
len = strlen((char *) (Args[ARG_PLAYCDDA]));
if (len >= sizeof (g_play_cdda_command)) {
Display_Error ("PLAYCDDA command name too long");
result = FALSE;
} else
strcpy (g_play_cdda_command, (char *) (Args[ARG_PLAYCDDA]));
} else
g_play_cdda_command[0] = 0;
if (Args[ARG_XPOS])
g_xpos = *(long *) (Args[ARG_XPOS]);
if (Args[ARG_YPOS])
g_ypos = *(long *) (Args[ARG_YPOS]);
FreeArgs(ArgsPtr);
} else {
Fault(IoErr (), (UBYTE *) "", LocalBuffer, sizeof (LocalBuffer));
Display_Error ("Error while parsing \"Startup\" field in Mountlist:\n%s",
LocalBuffer + 2);
}
FreeDosObject (DOS_RDARGS, ArgsPtr);
} else
Display_Error ("Out of memory");
if (result) {
if (!(g_cd = Open_CDROM (g_device, g_unit, g_trackdisk, g_memory_type,
g_std_buffers, g_file_buffers))) {
switch (g_cdrom_errno) {
case CDROMERR_NO_MEMORY:
Display_Error ("Out of memory: cannot allocate buffers\n"
"(Try CHIP, FAST, DMA or ANY option.)");
break;
case CDROMERR_MSGPORT:
Display_Error ("Cannot open the message port.");
break;
case CDROMERR_IOREQ:
Display_Error ("Cannot open the I/O request structure.");
break;
case CDROMERR_DEVICE:
Display_Error ("Cannot open \"%s\" unit %ld", g_device, (int) g_unit);
break;
case CDROMERR_BLOCKSIZE:
Display_Error ("Cannot access CDROM drive: illegal blocksize.");
break;
default:
break;
}
result = FALSE;
}
}
return result;
}
int Handle_Control_Packet (ULONG p_type, ULONG p_par1, ULONG p_par2)
{
switch (p_type) {
case CDCMD_LOWERCASE:
g_map_to_lowercase = p_par1;
break;
case CDCMD_MACTOISO:
g_convert_hfs_filenames = p_par1;
break;
case CDCMD_CONVERTSPACES:
g_convert_hfs_spaces = p_par1;
break;
case CDCMD_SHOWVERSION:
g_show_version_numbers = p_par1;
break;
case CDCMD_HFSFIRST:
g_hfs_first = p_par1;
break;
case CDCMD_DATAEXT:
strcpy (g_data_fork_extension, (char *) p_par1);
break;
case CDCMD_RESOURCEEXT:
strcpy (g_resource_fork_extension, (char *) p_par1);
break;
default:
return 999;
}
return 0;
}
#ifdef _DCC
extern void debugproc (void);
#if defined(NDEBUG) && !defined(DEBUG_SECTORS)
void debugmain (void) {;}
#endif
#endif
#if !defined(NDEBUG) || defined(DEBUG_SECTORS)
char *typetostr (int ty)
{
switch(ty) {
case ACTION_DIE: return("DIE");
case ACTION_FINDUPDATE: return("OPEN-RW");
case ACTION_FINDINPUT: return("OPEN-OLD");
case ACTION_FINDOUTPUT: return("OPEN-NEW");
case ACTION_READ: return("READ");
case ACTION_WRITE: return("WRITE");
case ACTION_END: return("CLOSE");
case ACTION_SEEK: return("SEEK");
case ACTION_EXAMINE_NEXT: return("EXAMINE NEXT");
case ACTION_EXAMINE_OBJECT: return("EXAMINE OBJ");
case ACTION_INFO: return("INFO");
case ACTION_DISK_INFO: return("DISK INFO");
case ACTION_PARENT: return("PARENTDIR");
case ACTION_DELETE_OBJECT: return("DELETE");
case ACTION_CREATE_DIR: return("CREATEDIR");
case ACTION_LOCATE_OBJECT: return("LOCK");
case ACTION_COPY_DIR: return("DUPLOCK");
case ACTION_FREE_LOCK: return("FREELOCK");
case ACTION_SET_PROTECT: return("SETPROTECT");
case ACTION_SET_COMMENT: return("SETCOMMENT");
case ACTION_RENAME_OBJECT: return("RENAME");
case ACTION_INHIBIT: return("INHIBIT");
case ACTION_RENAME_DISK: return("RENAME DISK");
case ACTION_MORE_CACHE: return("MORE CACHE");
case ACTION_WAIT_CHAR: return("WAIT FOR CHAR");
case ACTION_FLUSH: return("FLUSH");
case ACTION_SCREEN_MODE: return("SCREENMODE");
case ACTION_IS_FILESYSTEM: return("IS_FILESYSTEM");
case ACTION_SAME_LOCK: return("SAME_LOCK");
case ACTION_COPY_DIR_FH: return("COPY_DIR_FH");
case ACTION_PARENT_FH: return("PARENT_FH");
case ACTION_EXAMINE_FH: return("EXAMINE_FH");
case ACTION_FH_FROM_LOCK: return("FH_FROM_LOCK");
case ACTION_CURRENT_VOLUME: return("CURRENT_VOLUME");
case ACTION_READ_LINK: return("READ LINK");
case ACTION_USER: return("USER");
default: return("---------UNKNOWN-------");
}
}
/*
* DEBUGGING CODE. You cannot make DOS library calls that access other
* devices from within a DOS device driver because they use the same
* message port as the driver. If you need to make such calls you must
* create a port and construct the DOS messages yourself. I do not
* do this. To get debugging info out another PROCESS is created to which
* debugging messages can be sent.
*
* You want the priority of the debug process to be larger than the
* priority of your DOS handler. This is so if your DOS handler crashes
* you have a better idea of where it died from the debugging messages
* (remember that the two processes are asyncronous from each other).
*/
/*
* BTW, the DOS library used by debugmain() was actually opened by
* the device driver. Note: DummyMsg cannot be on debugmain()'s stack
* since debugmain() goes away on the final handshake.
*/
#ifdef LATTICE
void __saveds debugmain (void)
#else
void debugmain (void)
#endif /* LATTICE */
{
MSG *msg;
short len;
void *fh;
#ifdef LOG_MESSAGES
void *out;
#endif
#ifdef AZTEC_C
extern void geta4 (void);
geta4();
#endif
Dbport = CreateMsgPort ();
fh = (void *) Open ((UBYTE *) "con:0/0/640/100/debugwindow", 1006);
PutMsg(Dback, &DummyMsg);
#ifdef LOG_MESSAGES
#ifdef LOG_TO_PAR
out = (void *) Open ((UBYTE *) "PAR:", 1006);
#else
out = (void *) Open ((UBYTE *) "ram:cd.log", 1006);
#endif
#endif
for (;;) {
WaitPort(Dbport);
msg = GetMsg(Dbport);
len = msg->mn_Length;
if (len == 0)
break;
--len; /* Fix length up */
Write((BPTR) fh, msg+1, len);
#ifdef LOG_MESSAGES
Write((BPTR) out, msg+1, len);
#endif
FreeMem(msg,sizeof(MSG)+len+1);
}
Close ((BPTR) fh);
#ifdef LOG_MESSAGES
Close ((BPTR) out);
#endif
DeleteMsgPort(Dbport);
PutMsg(Dback,&DummyMsg); /* Kill handshake */
}
void dbinit (void)
{
TASK *task = FindTask(NULL);
Dback = CreateMsgPort();
if (CreateNewProcTags (
#ifdef _DCC
NP_Seglist, (BPTR) (CTOB(debugproc)),
#else
NP_Entry, debugmain,
#endif
NP_Name, "DEV_DB",
NP_Priority, task->tc_Node.ln_Pri+1,
NP_StackSize, 4096,
TAG_DONE)) {
WaitPort(Dback); /* handshake startup */
GetMsg(Dback); /* remove dummy msg */
dbprintf("Debugger running: %s, %s\n", TheVersion+6, __TIME__);
};
}
void dbuninit (void)
{
MSG killmsg;
if (Dbport) {
killmsg.mn_Length = 0; /* 0 means die */
PutMsg(Dbport,&killmsg);
WaitPort(Dback); /* He's dead jim! */
GetMsg(Dback);
DeleteMsgPort(Dback);
/*
* Since the debug process is running at a greater priority, I
* am pretty sure that it is guarenteed to be completely removed
* before this task gets control again. Still, it doesn't hurt...
*/
Delay(100); /* ensure he's dead */
}
}
void dbprintf (char *format, ...)
{
va_list arg;
char buf[256];
MSG *msg;
va_start (arg, format);
if (Dbport && !DBDisable) {
vsprintf (buf, format, arg);
msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
msg->mn_Length = strlen(buf)+1; /* Length NEVER 0 */
strcpy((char *) (msg+1), buf);
PutMsg(Dbport,msg);
}
va_end (arg);
}
#endif /* !NDEBUG || DEBUG_SECTORS */